- 
                Notifications
    
You must be signed in to change notification settings  - Fork 2.7k
 
QUCOL Onboarding #993
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 19.0
Are you sure you want to change the base?
QUCOL Onboarding #993
Conversation
46fe336    to
    5cda5fe      
    Compare
  
    ad8ec7f    to
    3a01b0f      
    Compare
  
    d0a617c    to
    0cf2ff3      
    Compare
  
    eff89b1    to
    2faaaee      
    Compare
  
    There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @qucol-odoo 👋,
Here is a review of your code. You went through the tutorials without much difficulty so I've been a little bit more touchy on your PR 😃.
Your branch is very clean! And we're not going to dirty it. Then can you do the corrections in the right commits ? In the end, your branch shouldn't contain new commit. If you meet some issue doing it, ping me 😃.
Thanks for your job and for helping your teammates!
        
          
                estate/models/__init__.py
              
                Outdated
          
        
      | from . import estate_properties | ||
| from . import estate_property_types | ||
| from . import estate_property_tags | ||
| from . import estate_property_offers | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They should be listed alphabetically.
        
          
                estate/models/estate_property.py
              
                Outdated
          
        
      | DEFAULT_GARDEN_AREA = 10 | ||
| DEFAULT_GARDEN_ORIENTATION = "north" | ||
| 
               | 
          
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the right way to write constants but I am not sure to understand why it is required. They are used only in _update_garden_area_and_orientation, can they be defined directly in that method?
        
          
                estate/models/estate_property.py
              
                Outdated
          
        
      | selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')] | ||
| ) | ||
| total_living_area = fields.Integer(compute="_compute_total_area") | ||
| 
               | 
          
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need of that blank line 😃.
        
          
                estate/models/estate_properties.py
              
                Outdated
          
        
      | record.total_living_area = record.living_area + record.garden_area | ||
| 
               | 
          ||
| @api.depends("offer_ids") | ||
| def _get_highest_price(self): | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this method is used to compute the best_price, it should be named _compute_best_offer 😃, that way we know easily 1. it computes field and 2 which field.
FYI, _get or get methods should return an object and should not modify the database. For example, _get_res_user should only return a res_user and do nothing else.
        
          
                estate/models/estate_property.py
              
                Outdated
          
        
      | record.best_offer = max(record.offer_ids.mapped("price")) if record.offer_ids else 0 | ||
| 
               | 
          ||
| @api.onchange("garden") | ||
| def _update_garden_area_and_orientation(self): | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
| <field name="arch" type="xml"> | ||
| <form string="Property type"> | ||
| <sheet> | ||
| <button name="%(estate.estate_property_offer_action)d" string="Offers" type="action" title="Offers list" invisible="not offer_count > 0"/> | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <button name="%(estate.estate_property_offer_action)d" string="Offers" type="action" title="Offers list" invisible="not offer_count > 0"/> | |
| <button name="%(estate.estate_property_offer_action)d" string="Offers" type="action" title="Offers list" invisible="offer_count == 0"/> | 
| <field name="name"/> | ||
| </h1> | ||
| <group> | ||
| <field name="offer_count"/> | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can test to add it inside your oe_stat_button ? (not a priority). You can find a solution here (line 847)
| @@ -0,0 +1,21 @@ | |||
| <odoo> | |||
| <record id="estate_res_user_view_form" model="ir.ui.view"> | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can call it as its parent. Other modules will refer to this one as estate.res_user_view_form. So here we know that the main form of the user has been modified and this is not a new one.
| <record id="estate_res_user_view_form" model="ir.ui.view"> | |
| <record id="res_user_view_form" model="ir.ui.view"> | 
        
          
                estate/__manifest__.py
              
                Outdated
          
        
      | ], | ||
| 'data': [ | ||
| 'security/ir.model.access.csv', | ||
| 
               | 
          
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need of this blank line. Do not forget that a lot of developers are working on the project and we must avoid unnecessary changes.
| taken_ids = set() | ||
| for invoice in self.env["account.move"].search([]): | ||
| if (match := re.match(r"Invoice\s+(\d+)", invoice.name)): | ||
| taken_ids.add(int(match.group(1))) | ||
| i = 1 | ||
| while i in taken_ids: | ||
| i += 1 | ||
| return f"Invoice {i}" | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to select the first number missing in the sequence or the one above the maximum ?
If it is the last case, I would do something like that to avoid too many loops.
| taken_ids = set() | |
| for invoice in self.env["account.move"].search([]): | |
| if (match := re.match(r"Invoice\s+(\d+)", invoice.name)): | |
| taken_ids.add(int(match.group(1))) | |
| i = 1 | |
| while i in taken_ids: | |
| i += 1 | |
| return f"Invoice {i}" | |
| invoice = self.env["account.move"].search([("name", "like", "Invoice %")], order='id desc', limit=1) | |
| if invoice and (match := re.match(r"Invoice (\d+)", invoice.name)): | |
| return f"Invoice {match.group(1)}" | |
| return "Invoice 1" | 
327b3f5    to
    2a0540b      
    Compare
  
    2eeb5b3    to
    7784a59      
    Compare
  
    7784a59    to
    3e9e034      
    Compare
  
    There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @qucol-odoo 😃,
Just a quick review. Those changes are not a priority as we are arriving at the end of the onboarding. It's just to let you know about other good practices.
About the title of your PR, its pattern is the same as the one of the commits. [IMP/FIX/ADD/...]: applications: what the PR is doing (starting with a verb). Here for the applications you could write estate{_account}. We use {} to avoid estate, estate_account. We squash them. And if there are to much app, you just write * in the title and in the description you write * = all the names of the apps.
And for the description you should summarize the content of your commits.  The description must mainly explain why you are doing your modifications and not how you reached the goal.
Once again no need to change it now, it's just for you to know.
Cheers !
        
          
                estate/tests/test_estate_property.py
              
                Outdated
          
        
      | def create_sold_property(cls): | ||
| cls.sold_property = cls.env["estate.property"].create([{ | ||
| "name": "Sold Property", | ||
| "state": "new", | ||
| "expected_price": 4000.0 | ||
| }]) | ||
| cls.env["estate.property.offer"].create([{ | ||
| "partner_id": ADMINISTRATOR_ID, | ||
| "property_id": cls.sold_property.id, | ||
| "status": "accepted", | ||
| "price": 4000.0 | ||
| }]) | ||
| cls.sold_property.state = "sold" | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should create functions/methods only if they are used several times or overridden. I must say that before Odoo I liked creating functions because according to me, it made the code more readable. But they asked me to stop 😅 because it creates a ping pong effect and you should be able to read as much code as possible at once.
        
          
                estate/tests/test_estate_property.py
              
                Outdated
          
        
      | from odoo.tests import tagged, Form | ||
| 
               | 
          ||
| 
               | 
          ||
| ADMINISTRATOR_ID = 3 | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Data created in xml/csv have an external_id. This is the id of the xml record. It can be easily found. For example here you can search `model="res.partner"' in all your xml files and then you can check the demo data.
When you need to cache a record by its id you can used the ref method of self.env. It contacts the ir_model_data table which contains all the external ids and with the other information of the record in that table its able to find where is the record asked.
Also we usually do not write global constants. So you could just put it inside the setUpClass.
| ADMINISTRATOR_ID = 3 | |
| ADMINISTRATOR_ID = self.env.ref("base.partner_admin").id | 
        
          
                estate/tests/test_estate_property.py
              
                Outdated
          
        
      | for offer in correct_offers: | ||
| try: | ||
| self.env["estate.property.offer"].create([offer]) | ||
| except UserError: | ||
| self.fail() | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to catch the exception 😃, or maybe I'm missing something. If an exception occurs the test doesn't pass. As it can make a code a bit less readable, do not hesitate to write why you do that. Do not forget always why and not how as every developer should be able to read your code, but sometimes the purpose may not be clear.
| <field name="postcode"/> | ||
| <field name="expected_price"/> | ||
| <field name="bedrooms"/> | ||
| <field name="living_area" filter_domain="['|', ('living_area', '=', self), ('living_area', '>', self)]"/> | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you do this?
| <field name="living_area" filter_domain="['|', ('living_area', '=', self), ('living_area', '>', self)]"/> | |
| <field name="living_area" filter_domain="[('living_area', '>=', self)]"/> | 
3e9e034    to
    601b9a6      
    Compare
  
    
No description provided.